#ifndef _892b7eda_6d2d_46f4_aa77_fb5d798df337__MUTEX_H__
#define _892b7eda_6d2d_46f4_aa77_fb5d798df337__MUTEX_H__

#include "config.h"

#if defined(JELLY_WIN32) || defined(JELLY_WINCE)
#include <windows.h>
#elif  defined(JELLY_LINUX)
#include <pthread.h>
#endif

namespace threadmutex
{

template<typename T>
class Lock
{
public:
	Lock(T& t) :
			t_(t)
	{
		t_.lock();
	}
	~Lock()
	{
		t_.unlock();
	}
private:
	T& t_;
};

class NoMutex
{
public:
	void lock()
	{
	}
	void unlock()
	{
	}
};

#if defined(WIN32)
class CriticalSectionMutex
{
public:
	CriticalSectionMutex()
	{
		::InitializeCriticalSection(&cs_);
	}
	~CriticalSectionMutex()
	{
		::DeleteCriticalSection(&cs_);
	}
	inline void lock()
	{
		::EnterCriticalSection(&cs_);
	}
	inline void unlock()
	{
		::LeaveCriticalSection(&cs_);
	}
	struct innerLock
	{
		innerLock(CriticalSectionMutex* p)
		{
			p->lock();
			p_ = p;
		}
		~innerLock()
		{
			p_->unlock();
		}
		CriticalSectionMutex* p_;
	};

private:
	explicit CriticalSectionMutex(const CriticalSectionMutex&);
	CriticalSectionMutex& operator=(const CriticalSectionMutex&);
	CRITICAL_SECTION cs_;
};
#else
class pthread_mutex
{
public:
	pthread_mutex():mutex_(PTHREAD_MUTEX_INITIALIZER)
	{
	}
	~pthread_mutex()
	{
		pthread_mutex_destroy(&mutex_);
	}
	void lock()
	{
		pthread_mutex_lock(&mutex_);
	}
	void unlock()
	{
		pthread_mutex_unlock(&mutex_);
	}
	struct innerLock
	{
		innerLock(pthread_mutex* p)
		{
			p->lock();
			p_ = p;
		}
		~innerLock()
		{
			p_->unlock();
		}
		pthread_mutex* p_;
	};
private:
	explicit pthread_mutex(const pthread_mutex&);
	pthread_mutex& operator=(const pthread_mutex&);
	pthread_mutex_t mutex_;
};
#endif

}

#endif //_892b7eda_6d2d_46f4_aa77_fb5d798df337__MUTEX_H__
